package com.d.lib.ui.view.progress;

import com.d.lib.ui.view.ResourceTable;
import com.makeramen.roundedimageview.RoundedImageView;
import java.io.InputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ElementScatter;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;

/**
 * SnapProgressBar
 * Created by D on 2018/3/30.
 */
public class SnapProgressBar extends StackLayout implements Component.ClickedListener,
    Component.DrawTask, Component.EstimateSizeListener {
  public final static int STATE_SCANNING = 0;
  public final static int STATE_PROGRESS = 1;
  public final static int STATE_PENDDING = 2;
  public final static int STATE_DONE = 3;
  public final static int STATE_ERROR = 4;

  /**
   * [0]: Scanning
   * [1]: Progress
   * [2]: Pendding
   * [3]: Done
   * [4]: Error
   */
  private final int[] RES_IDS = new int[]{ResourceTable.Media_lib_ui_view_vs_icon,
      Color.getIntColor("#00000000"),
      ResourceTable.Media_lib_ui_view_rtv_ic_back,
      ResourceTable.Media_lib_ui_view_vs_icon,
      ResourceTable.Media_lib_ui_view_vs_icon};

  private int mWidth, mHeight;

  private Context mContext;
  private Paint mPaint;

  private Rect mRect;
  private RectFloat mRectF;
  private int mColorCircle, mColorArc;
  private int mDiameter;
  private int mSpace;
  private int[] mPaddingIcon;

  private float mFactor;

  private int mState = STATE_SCANNING;
  private boolean mIsFirst = true;
  private Request mRequest;
  private RoundedImageView mIvThumb, mIvState;
  private RoundedImageView mIvAlpha;
  private OnClickListener mListener;

  public SnapProgressBar(Context context) {
    this(context, null);
  }

  public SnapProgressBar(Context context, AttrSet attrs) {
    this(context, attrs, null);
  }

  public SnapProgressBar(Context context, AttrSet attrs, String defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initAttrs(context, attrs);
    init(context);
  }

  private void initAttrs(Context context, AttrSet attrs) {
    mColorCircle = Color.getIntColor("#33008577");
    mColorArc = Color.getIntColor("#ff008577");
    mSpace = AttrHelper.fp2px(2.5f, context);
    mPaddingIcon = new int[]{AttrHelper.fp2px(21.5f, context),
        AttrHelper.fp2px(20f, context)};
  }

  private void init(Context context) {
    this.mContext = context;
//        this.setWillNotDraw(false);
    // 外圈
    LayoutConfig lp;
    mIvThumb = new RoundedImageView(context);
    mIvThumb.setOval(true);
    mIvThumb.setScaleMode(Image.ScaleMode.CLIP_CENTER);
    lp = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
        ComponentContainer.LayoutConfig.MATCH_PARENT);
    lp.alignment = TextAlignment.CENTER;
    addComponent(mIvThumb, lp);

    // 背景
    mIvAlpha = new RoundedImageView(context);
    mIvAlpha.setOval(true);
    mIvAlpha.setScaleMode(Image.ScaleMode.CLIP_CENTER);
    ShapeElement shapeElement = new ShapeElement();
    shapeElement.setCornerRadius(80);
    shapeElement.setRgbColor(RgbColor.fromArgbInt(Color.getIntColor("#9900040a")));
    mIvAlpha.setImageElement(shapeElement);
    lp = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
        ComponentContainer.LayoutConfig.MATCH_PARENT);
    lp.alignment = TextAlignment.CENTER;
    addComponent(mIvAlpha, lp);

    // 图
    mIvState = new RoundedImageView(context);
    mIvState.setOval(true);
    mIvState.setScaleMode(Image.ScaleMode.CLIP_CENTER);
    lp = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
        ComponentContainer.LayoutConfig.MATCH_PARENT);
    lp.alignment = TextAlignment.CENTER;
    addComponent(mIvState, lp);
    mIvState.setClickedListener(this);

    mRequest = new Request();
    mPaint = new Paint();
    mPaint.setColor(new Color(mColorCircle));
    mPaint.setStrokeWidth(mSpace);
    mPaint.setStyle(Paint.Style.STROKE_STYLE);

    mRect = new Rect();
    mRectF = new RectFloat();

    addDrawTask(this::onDraw);
    setEstimateSizeListener(this::onEstimateSize);
  }

  /**
   * 通过资源ID获取位图对象
   **/
  private PixelMap getPixelMap(int resId) {
    InputStream drawableInputStream = null;
    try {
      drawableInputStream = getResourceManager().getResource(resId);
      ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
      sourceOptions.formatHint = "image/png";
      ImageSource imageSource = ImageSource.create(drawableInputStream, null);
      ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
      decodingOptions.desiredSize = new Size(0, 0);
      decodingOptions.desiredRegion = new ohos.media.image.common.Rect(0, 0, 0, 0);
      decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
      PixelMap pixelMap = imageSource.createPixelmap(decodingOptions);
      return pixelMap;
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        if (drawableInputStream != null) {
          drawableInputStream.close();
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    return null;
  }

  @Override
  public void onDraw(Component component, Canvas canvas) {
    if (mState != STATE_PROGRESS && mState != STATE_PENDDING) {
      return;
    }
    mRect.set((int) ((mWidth - mDiameter) / 2f + mSpace / 2f),
        (int) ((mHeight - mDiameter) / 2f + mSpace / 2f),
        mWidth - (int) ((mWidth - mDiameter) / 2f + mSpace / 2f),
        mHeight - (int) ((mHeight - mDiameter) / 2f + mSpace / 2f));
    mRectF.modify(mRect);
    mPaint.setColor(new Color(mColorCircle));
    mPaint.setStrokeCap(Paint.StrokeCap.BUTT_CAP);
    canvas.drawArc(mRectF, new Arc(-90, 360, false), mPaint);
    mPaint.setColor(new Color(mColorArc));
    mPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
    canvas.drawArc(mRectF, new Arc(-90, mFactor, false), mPaint);
  }

  @Override
  public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
    mWidth = EstimateSpec.getSize(widthMeasureSpec);
    mHeight = EstimateSpec.getSize(heightMeasureSpec);
    mDiameter = Math.min(mWidth, mHeight);
    mPaddingIcon[0] = (int) (mDiameter * 20f / 60f);
    mPaddingIcon[1] = (int) (mDiameter * 20f / 60f);
    mIvThumb.setPadding((int) ((mWidth - mDiameter) / 2f + mSpace),
        (int) ((mHeight - mDiameter) / 2f + mSpace),
        (int) ((mWidth - mDiameter) / 2f + mSpace), (int) ((mHeight - mDiameter) / 2f + mSpace));
    mIvAlpha.setPadding((int) ((mWidth - mDiameter) / 2f + mSpace),
        (int) ((mHeight - mDiameter) / 2f + mSpace),
        (int) ((mWidth - mDiameter) / 2f + mSpace), (int) ((mHeight - mDiameter) / 2f + mSpace));
    int count = getChildCount();
    for (int i = 0; i < count; i++) {
      Component child = getComponentAt(i);
      child.estimateSize(EstimateSpec.getSizeWithMode(widthMeasureSpec, EstimateSpec.PRECISE),
          EstimateSpec.getSizeWithMode(heightMeasureSpec, EstimateSpec.PRECISE));
    }
    setEstimatedSize(EstimateSpec.getSizeWithMode(mWidth, EstimateSpec.PRECISE),
        EstimateSpec.getSizeWithMode(mHeight, EstimateSpec.PRECISE));
    if (mIsFirst && mDiameter > 0) {
      mIsFirst = false;
      setState(mState);
    }
    return true;
  }

  @Override
  public void onClick(Component component) {
    if (component.equals(mIvState)) {
      switch (mState) {
        case STATE_PENDDING:
          if (mListener != null) {
            mListener.onRestart();
          }
          break;
      }
    }
  }

  public Request setState(@State int state) {
    this.mState = state;
    switch (state) {
      case STATE_SCANNING:
        mIvThumb.setVisibility(HIDE);
        mIvAlpha.setVisibility(HIDE);
        mIvState.setVisibility(VISIBLE);
        mIvState.setPadding((int) ((mWidth - mDiameter) / 2f), (int) ((mHeight - mDiameter) / 2f),
            (int) ((mWidth - mDiameter) / 2f), (int) ((mHeight - mDiameter) / 2f));
        mIvState.setPixelMap(ResourceTable.Media_lib_ui_view_vs_icon);
        break;
      case STATE_PROGRESS:
        mIvThumb.setVisibility(VISIBLE);
        mIvAlpha.setVisibility(HIDE);
        mIvState.setVisibility(HIDE);
        break;
      case STATE_PENDDING:
        // 外部 圆圈
        mIvThumb.setVisibility(VISIBLE);
        // 内背景
        mIvAlpha.setVisibility(VISIBLE);
        // 内图
        mIvState.setVisibility(VISIBLE);
        mIvState.setPadding((int) ((mWidth - mDiameter) / 2f + mPaddingIcon[0]),
            (int) ((mHeight - mDiameter) / 2f + mPaddingIcon[1]),
            (int) ((mWidth - mDiameter) / 2f + mPaddingIcon[0]),
            (int) ((mHeight - mDiameter) / 2f + mPaddingIcon[1]));
        mIvState.setPixelMap(ResourceTable.Media_lib_ui_view_rtv_ic_back);
        break;
      case STATE_DONE:
        mIvThumb.setVisibility(HIDE);
        mIvAlpha.setVisibility(HIDE);
        mIvState.setVisibility(VISIBLE);
        mIvState.setPadding((int) ((mWidth - mDiameter) / 2f), (int) ((mHeight - mDiameter) / 2f),
            (int) ((mWidth - mDiameter) / 2f), (int) ((mHeight - mDiameter) / 2f));
        mIvState.setPixelMap(RES_IDS[STATE_DONE]);
        break;
      case STATE_ERROR:
        mIvThumb.setVisibility(HIDE);
        mIvAlpha.setVisibility(HIDE);
        mIvState.setVisibility(VISIBLE);
        mIvState.setPadding((int) ((mWidth - mDiameter) / 2f), (int) ((mHeight - mDiameter) / 2f),
            (int) ((mWidth - mDiameter) / 2f), (int) ((mHeight - mDiameter) / 2f));
        mIvState.setPixelMap(RES_IDS[STATE_ERROR]);
        break;
    }
    return mRequest;
  }

  public void image(Image view, int id) {
    view.setImageElement(ElementScatter.getInstance(getContext()).parse(id));
  }

  public void setOnClickListener(OnClickListener l) {
    this.mListener = l;
  }

  @Target({ElementType.PARAMETER})
  @Retention(RetentionPolicy.SOURCE)
  public @interface State {

  }

  public interface OnClickListener {
    void onRestart();
  }

  public class Request {
    public Request thumb(int bitmap) {
//            mIvThumb.setPadding(80, 80, 80, 80);
      mIvThumb.setImageAndDecodeBounds(bitmap);
      return this;
    }

    public Request thumb(Element drawable) {
      mIvThumb.setImageElement(drawable);
      return this;
    }

    public Request thumb(PixelMap drawable) {
      mIvThumb.setPixelMap(drawable);
      return this;
    }

    public Request progress(float progress) {
      mFactor = 360 * progress;
      invalidate();
      return this;
    }
  }
}
